#include "CompactPrimitive.h"

CompactPrimitive::CompactPrimitive (UINT elemNum,
		QD3DResourcePack *p_dataPack, QD3DResourcePack *p_marksPack,
		QD3DResourcePack *p_compactedPack, const std::string &structBufType,
		const std::string &customStructDeclare) :
		_rp_dataPack (p_dataPack), _rp_marksPack (p_marksPack),
		_rp_compactedPack (p_compactedPack), _elemNum (elemNum)
{
	QD3DUtils d3DUtils;

	_p_totalNumDxConstBuf = d3DUtils.createConstBuffer ((ConstVars*)NULL);

	QD3DShaderDesc shaderDesc;
	shaderDesc.setDefine ("TYPE", structBufType);
	shaderDesc.setDefine ("TYPE_DECLARE", customStructDeclare);
	shaderDesc.setDefine ("TG_SIZE", "64");
	_p_compactCS = d3DUtils.createShaderFromFile< ID3D11ComputeShader > (
			QD3DUtils::COMPUTE_SHADER, "cs_5_0",
			"..\\Data\\Shaders\\Primitives\\CompactCS.hlsl", "csMain", shaderDesc);

	_p_scanPrimitive = new ScanPrimitive (
			elemNum, _rp_marksPack, sizeof (UINT), "uint");
}

CompactPrimitive::~CompactPrimitive ()
{
	SAFE_RELEASE (_p_totalNumDxConstBuf);
	SAFE_RELEASE (_p_compactCS);
	delete _p_scanPrimitive;
}

void CompactPrimitive::run (UINT elemNum)
{
	_p_scanPrimitive->run (elemNum);

	if (elemNum == -1)
		elemNum = _elemNum;

	QD3DUtils d3DUtils;
	ConstVars constVars;
	constVars.var.totalElemNum = elemNum;
	d3DUtils.updateSubresource (_p_totalNumDxConstBuf, 0, &constVars);

	QVector< ID3D11Buffer * > dxConstBufPtrs (1);
	QVector< ID3D11ShaderResourceView * > dxSRVPtrs (2);
	QVector< ID3D11UnorderedAccessView * > dxUAVPtrs (1);

	dxConstBufPtrs[0] = _p_totalNumDxConstBuf;
	d3DUtils.setConstBufs (QD3DUtils::COMPUTE_SHADER, 0, dxConstBufPtrs);
	dxSRVPtrs[0] = _rp_dataPack->getSRV ();
	dxSRVPtrs[1] = _rp_marksPack->getSRV ();
	d3DUtils.setSRVs (QD3DUtils::COMPUTE_SHADER, 0, dxSRVPtrs);
	dxUAVPtrs[0] = _rp_compactedPack->getUAV ();
	d3DUtils.setUAVs (QD3DUtils::COMPUTE_SHADER, 0, dxUAVPtrs);

	d3DUtils.setComputeShader (_p_compactCS);
	d3DUtils.dispatch (ceil (elemNum / 64.0), 1, 1);

	d3DUtils.clearConstBufs (QD3DUtils::COMPUTE_SHADER, 0,
			dxConstBufPtrs.size ());
	d3DUtils.clearSRVs (QD3DUtils::COMPUTE_SHADER, 0, dxSRVPtrs.size ());
	d3DUtils.clearUAVs (QD3DUtils::COMPUTE_SHADER, 0, dxUAVPtrs.size ());
}